package lelouet.datacenter.simulation;

import java.util.Set;

import lelouet.datacenter.simulation.factorized.WorkingElement;
import lelouet.datacenter.simulation.vms.AVM;

/**
 * An hypervisor manages a set of {@link AVM} that use its resources.<br />
 * Resources are memory(in Mo) and frequency(in MIPs)<br />
 * A correct use of an hypervisor is :
 * <ol>
 * <li>create it</li>
 * <li>manage it or its VMs</li>
 * <li>{@link #reconfigure() reconfigure it}</li>
 * <li>get its {@link #nextEventTime() next event time}</li>
 * <li>{@link #work(long) make it work} till its next event time or before</li>
 * <li>handle resulting events</li>
 * <li>goto 2</li>
 * </ol>
 * <em> Note :</em> the {@link #reconfigure()} method must be called before any
 * {@link #nextEventTime()} or {@link #work(long)} if there has been any
 * modification to the hypervisor or its VMs since last {@link #reconfigure()} .
 * most of the function of this class modify the hypervisor, but the getters
 * don't.<br />
 * 
 * 
 * @author lelouet
 */
public interface Hypervisor extends WorkingElement {

	/** reboot this at given time */
	public void restart(long time);

	/**
	 * set the memory available to VMs in this
	 * 
	 * @param mo
	 *            the size of memory, in Mo
	 */
	public void setVMsDedicatedMem(long mo);

	/** @return the memory that is available for VMs, in Mo */
	public long getVMsDedicatedMem();

	/** @return the total memory, in Mo, the {@link VM}s in this are using */
	public long getVMsAllocatedMem();

	/**
	 * set the total Million Instructions Per Second this allocates to the VMs
	 * it manages
	 */
	public void setVMsDedicatedCPU(long mips);

	/**
	 * @return he total Million Instructions Per Second this allocates to the
	 *         VMs it manages
	 */
	public long getVMsDedicatedCPU();

	/**
	 * start a VM if it is suspended on this
	 * 
	 * @return was there a suspended VM with such an ID in this ?
	 */
	public boolean startVM(VM vm);

	/**
	 * suspend a {@link VM} on this. If it was not present on this, it is added
	 * to the local {@link VM}s
	 * 
	 * @return was that VM absent or running on this ?
	 */
	public boolean suspendVM(VM vm);

	/**
	 * Remove the VM from those allocated on this
	 * 
	 * @return was there this vm on this ?
	 */
	public boolean removeVM(VM vm);

	/** @return an unmodifiable set of VMs that are suspended on this */
	public Set<VM> suspendedVMs();

	/** @return an unmodifiable set of the VMs that have been allocated to this. */
	public Set<VM> presentVMs();

}
